package org.example.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.example.entity.MallRepayPlan;
import org.example.entity.MallUserInfo;
import org.example.mapper.RepayPlanMapper;
import org.example.mapper.UserInfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 贷款数据更新服务
 * 用于批量更新放款时间和还款计划
 */
@Slf4j
@Service
public class LoanDataUpdateService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private RepayPlanMapper repayPlanMapper;
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    // 批量更新配置
    private static final int BATCH_SIZE = 500;

    /**
     * 更新放款时间从 2024 改为 2025
     * 将所有 2024-07-xx 的数据改为 2025-01-xx，保留时分秒
     */
    @Transactional(rollbackFor = Exception.class)
    public UpdateResult updateLoanTimeAndRepayPlan() {
        log.info("========== 开始更新放款时间和还款计划 ==========");
        long startTime = System.currentTimeMillis();
        
        UpdateResult result = new UpdateResult();
        int userInfoUpdated = 0;
        int repayPlanUpdated = 0;

        try {
            // 1. 查询所有需要更新的用户信息（2024-07开头的）
            LambdaQueryWrapper<MallUserInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.isNotNull(MallUserInfo::getLoanTime);
            
            List<MallUserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
            log.info("查询到 {} 条用户信息记录", userInfoList.size());

            // 2. 逐条更新用户信息的放款时间
            Map<String, LocalDateTime> orderTimeMap = new HashMap<>();
            
            for (MallUserInfo userInfo : userInfoList) {
                LocalDateTime oldLoanTime = userInfo.getLoanTime();
                if (oldLoanTime == null) {
                    continue;
                }

                // 检查是否是2024年7月的数据
                if (oldLoanTime.getYear() == 2024 && oldLoanTime.getMonthValue() == 7) {
                    // 提取原来的日期和时间
                    int day = oldLoanTime.getDayOfMonth();
                    LocalTime time = oldLoanTime.toLocalTime();
                    
                    // 创建新的日期时间：2025-01-xx，保留原来的日和时分秒
                    // 如果原来的日期是7月19日，改为1月2日
                    // 如果原来是7月20日，改为1月3日，以此类推
                    int newDay = day - 17; // 19-17=2, 20-17=3
                    if (newDay < 1) {
                        newDay = 1;
                    }
                    if (newDay > 31) {
                        newDay = 31;
                    }
                    
                    LocalDateTime newLoanTime = LocalDateTime.of(
                        LocalDate.of(2025, 1, newDay),
                        time
                    );

                    // 更新用户信息的放款时间
                    LambdaUpdateWrapper<MallUserInfo> updateWrapper = new LambdaUpdateWrapper<>();
                    updateWrapper.eq(MallUserInfo::getId, userInfo.getId())
                                .set(MallUserInfo::getLoanTime, newLoanTime);
                    
                    int updated = userInfoMapper.update(null, updateWrapper);
                    if (updated > 0) {
                        userInfoUpdated++;
                        orderTimeMap.put(userInfo.getOrderNumber(), newLoanTime);
                        
                        if (userInfoUpdated % 100 == 0) {
                            log.info("已更新用户信息 {} 条", userInfoUpdated);
                        }
                    }
                }
            }

            log.info("用户信息更新完成，共更新 {} 条", userInfoUpdated);

            // 3. 更新还款计划
            for (Map.Entry<String, LocalDateTime> entry : orderTimeMap.entrySet()) {
                String orderNumber = entry.getKey();
                LocalDateTime newLoanTime = entry.getValue();

                // 查询该订单的所有还款计划
                LambdaQueryWrapper<MallRepayPlan> planQueryWrapper = new LambdaQueryWrapper<>();
                planQueryWrapper.eq(MallRepayPlan::getOrderNumber, orderNumber)
                               .orderByAsc(MallRepayPlan::getPeriodNumber);
                
                List<MallRepayPlan> repayPlans = repayPlanMapper.selectList(planQueryWrapper);

                // 更新每期的还款计划
                // 设置截止日期：2025-09-30 23:59:59
                LocalDateTime cutoffDate = LocalDateTime.of(2025, 9, 30, 23, 59, 59);
                
                for (MallRepayPlan plan : repayPlans) {
                    Integer periodNumber = plan.getPeriodNumber();
                    if (periodNumber == null) {
                        continue;
                    }

                    // 计算新的到期时间 = 放款时间 + 期数（月）
                    LocalDateTime newDueTime = newLoanTime.plusMonths(periodNumber);

                    // 根据到期时间判断状态
                    LocalDateTime newActualRepayTime = null;
                    Integer newRepayStatus;
                    Integer newOverdueDays;
                    
                    if (newDueTime.isBefore(cutoffDate) || newDueTime.isEqual(cutoffDate)) {
                        // 到期时间在2025-09-30之前，按照原状态更新
                        Integer repayStatus = plan.getRepayStatus();
                        Integer overdueDays = plan.getOverdueDays();
                        
                        newRepayStatus = repayStatus;
                        newOverdueDays = overdueDays;

                        if (repayStatus != null) {
                            if (repayStatus == 2) {
                                // 正常还款，实际还款时间 = 到期时间
                                newActualRepayTime = newDueTime;
                            } else if (repayStatus == 3 && overdueDays != null && overdueDays > 0) {
                                // 逾期还款，实际还款时间 = 到期时间 + 逾期天数
                                newActualRepayTime = newDueTime.plusDays(overdueDays);
                            }
                        }
                    } else {
                        // 到期时间在2025-09-30之后，状态改为未到期
                        newRepayStatus = 0; // 0-未到期
                        newOverdueDays = 0;
                        newActualRepayTime = null;
                    }

                    // 更新还款计划
                    LambdaUpdateWrapper<MallRepayPlan> planUpdateWrapper = new LambdaUpdateWrapper<>();
                    planUpdateWrapper.eq(MallRepayPlan::getId, plan.getId())
                                    .set(MallRepayPlan::getDueTime, newDueTime)
                                    .set(MallRepayPlan::getRepayStatus, newRepayStatus)
                                    .set(MallRepayPlan::getOverdueDays, newOverdueDays);
                    
                    if (newActualRepayTime != null) {
                        planUpdateWrapper.set(MallRepayPlan::getActualRepayTime, newActualRepayTime);
                    } else {
                        planUpdateWrapper.set(MallRepayPlan::getActualRepayTime, null);
                    }

                    int updated = repayPlanMapper.update(null, planUpdateWrapper);
                    if (updated > 0) {
                        repayPlanUpdated++;
                    }
                }

                if (repayPlanUpdated % 1000 == 0) {
                    log.info("已更新还款计划 {} 条", repayPlanUpdated);
                }
            }

            log.info("还款计划更新完成，共更新 {} 条", repayPlanUpdated);

            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;

            result.setSuccess(true);
            result.setUserInfoUpdated(userInfoUpdated);
            result.setRepayPlanUpdated(repayPlanUpdated);
            result.setDuration(duration);
            result.setMessage(String.format("更新成功！用户信息更新 %d 条，还款计划更新 %d 条，耗时 %d ms",
                userInfoUpdated, repayPlanUpdated, duration));

            log.info("========== 数据更新完成 ==========");
            log.info("用户信息更新: {} 条", userInfoUpdated);
            log.info("还款计划更新: {} 条", repayPlanUpdated);
            log.info("总耗时: {} ms", duration);

        } catch (Exception e) {
            log.error("更新数据失败", e);
            result.setSuccess(false);
            result.setMessage("更新失败: " + e.getMessage());
            throw e;
        }

        return result;
    }

    /**
     * 更新指定日期范围的放款时间
     * @param oldStartDate 原开始日期，如 "2024-07-19"
     * @param oldEndDate 原结束日期，如 "2024-07-31"
     * @param newStartDate 新开始日期，如 "2025-01-02"
     */
    @Transactional(rollbackFor = Exception.class)
    public UpdateResult updateLoanTimeByDateRange(String oldStartDate, String oldEndDate, String newStartDate) {
        log.info("========== 开始按日期范围更新放款时间 ==========");
        log.info("原日期范围: {} ~ {}", oldStartDate, oldEndDate);
        log.info("新开始日期: {}", newStartDate);
        
        long startTime = System.currentTimeMillis();
        UpdateResult result = new UpdateResult();
        int userInfoUpdated = 0;
        int repayPlanUpdated = 0;

        try {
            LocalDate oldStart = LocalDate.parse(oldStartDate);
            LocalDate oldEnd = LocalDate.parse(oldEndDate);
            LocalDate newStart = LocalDate.parse(newStartDate);

            // 计算日期偏移量
            long dayOffset = java.time.temporal.ChronoUnit.DAYS.between(oldStart, newStart);

            // 查询指定日期范围内的用户信息
            LambdaQueryWrapper<MallUserInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.isNotNull(MallUserInfo::getLoanTime);
            
            List<MallUserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
            Map<String, LocalDateTime> orderTimeMap = new HashMap<>();

            for (MallUserInfo userInfo : userInfoList) {
                LocalDateTime oldLoanTime = userInfo.getLoanTime();
                if (oldLoanTime == null) {
                    continue;
                }

                LocalDate loanDate = oldLoanTime.toLocalDate();
                
                // 检查是否在指定日期范围内
                if ((loanDate.isEqual(oldStart) || loanDate.isAfter(oldStart)) && 
                    (loanDate.isEqual(oldEnd) || loanDate.isBefore(oldEnd))) {
                    
                    // 计算新的放款时间
                    LocalDateTime newLoanTime = oldLoanTime.plusDays(dayOffset);

                    // 更新用户信息
                    LambdaUpdateWrapper<MallUserInfo> updateWrapper = new LambdaUpdateWrapper<>();
                    updateWrapper.eq(MallUserInfo::getId, userInfo.getId())
                                .set(MallUserInfo::getLoanTime, newLoanTime);
                    
                    int updated = userInfoMapper.update(null, updateWrapper);
                    if (updated > 0) {
                        userInfoUpdated++;
                        orderTimeMap.put(userInfo.getOrderNumber(), newLoanTime);
                    }
                }
            }

            log.info("用户信息更新完成，共更新 {} 条", userInfoUpdated);

            // 更新还款计划
            for (Map.Entry<String, LocalDateTime> entry : orderTimeMap.entrySet()) {
                String orderNumber = entry.getKey();
                LocalDateTime newLoanTime = entry.getValue();

                LambdaQueryWrapper<MallRepayPlan> planQueryWrapper = new LambdaQueryWrapper<>();
                planQueryWrapper.eq(MallRepayPlan::getOrderNumber, orderNumber)
                               .orderByAsc(MallRepayPlan::getPeriodNumber);
                
                List<MallRepayPlan> repayPlans = repayPlanMapper.selectList(planQueryWrapper);

                // 设置截止日期：2025-09-30 23:59:59
                LocalDateTime cutoffDate = LocalDateTime.of(2025, 9, 30, 23, 59, 59);
                
                for (MallRepayPlan plan : repayPlans) {
                    Integer periodNumber = plan.getPeriodNumber();
                    if (periodNumber == null) {
                        continue;
                    }

                    LocalDateTime newDueTime = newLoanTime.plusMonths(periodNumber);
                    
                    // 根据到期时间判断状态
                    LocalDateTime newActualRepayTime = null;
                    Integer newRepayStatus;
                    Integer newOverdueDays;
                    
                    if (newDueTime.isBefore(cutoffDate) || newDueTime.isEqual(cutoffDate)) {
                        // 到期时间在2025-09-30之前，按照原状态更新
                        Integer repayStatus = plan.getRepayStatus();
                        Integer overdueDays = plan.getOverdueDays();
                        
                        newRepayStatus = repayStatus;
                        newOverdueDays = overdueDays;

                        if (repayStatus != null) {
                            if (repayStatus == 2) {
                                newActualRepayTime = newDueTime;
                            } else if (repayStatus == 3 && overdueDays != null && overdueDays > 0) {
                                newActualRepayTime = newDueTime.plusDays(overdueDays);
                            }
                        }
                    } else {
                        // 到期时间在2025-09-30之后，状态改为未到期
                        newRepayStatus = 0; // 0-未到期
                        newOverdueDays = 0;
                        newActualRepayTime = null;
                    }

                    LambdaUpdateWrapper<MallRepayPlan> planUpdateWrapper = new LambdaUpdateWrapper<>();
                    planUpdateWrapper.eq(MallRepayPlan::getId, plan.getId())
                                    .set(MallRepayPlan::getDueTime, newDueTime)
                                    .set(MallRepayPlan::getRepayStatus, newRepayStatus)
                                    .set(MallRepayPlan::getOverdueDays, newOverdueDays);
                    
                    if (newActualRepayTime != null) {
                        planUpdateWrapper.set(MallRepayPlan::getActualRepayTime, newActualRepayTime);
                    } else {
                        planUpdateWrapper.set(MallRepayPlan::getActualRepayTime, null);
                    }

                    int updated = repayPlanMapper.update(null, planUpdateWrapper);
                    if (updated > 0) {
                        repayPlanUpdated++;
                    }
                }
            }

            log.info("还款计划更新完成，共更新 {} 条", repayPlanUpdated);

            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;

            result.setSuccess(true);
            result.setUserInfoUpdated(userInfoUpdated);
            result.setRepayPlanUpdated(repayPlanUpdated);
            result.setDuration(duration);
            result.setMessage(String.format("更新成功！用户信息更新 %d 条，还款计划更新 %d 条，耗时 %d ms",
                userInfoUpdated, repayPlanUpdated, duration));

            log.info("========== 数据更新完成 ==========");

        } catch (Exception e) {
            log.error("更新数据失败", e);
            result.setSuccess(false);
            result.setMessage("更新失败: " + e.getMessage());
            throw e;
        }

        return result;
    }

    /**
     * 批量修改放款时间（性能优化版）
     */
    @Transactional(rollbackFor = Exception.class)
    public UpdateResult batchUpdateLoanTimeByMonthMapping() {
        log.info("========== 开始批量修改放款时间（性能优化版） ==========");
        
        // 配置月份映射
        Map<String, String> monthMappings = buildMonthMappings();
        log.info("月份映射关系: {}", monthMappings);
        
        long startTime = System.currentTimeMillis();
        UpdateResult result = new UpdateResult();
        int userInfoUpdated = 0;
        int repayPlanUpdated = 0;

        try {
            // ===== 第一步：批量查询并计算用户信息更新数据 =====
            log.info("第一步：查询用户信息...");
            
            List<MallUserInfo> userInfoList = userInfoMapper.selectList(
                new LambdaQueryWrapper<MallUserInfo>().isNotNull(MallUserInfo::getLoanTime)
            );
            log.info("查询到 {} 条用户信息记录", userInfoList.size());

            // 批量计算新的放款时间，准备更新数据
            List<Object[]> userUpdateBatch = new ArrayList<>();
            Map<String, LocalDateTime> orderTimeMap = new HashMap<>();

            for (MallUserInfo userInfo : userInfoList) {
                LocalDateTime oldLoanTime = userInfo.getLoanTime();
                if (oldLoanTime == null) continue;

                String oldYearMonth = String.format("%04d-%02d", 
                    oldLoanTime.getYear(), oldLoanTime.getMonthValue());

                if (monthMappings.containsKey(oldYearMonth)) {
                    LocalDateTime newLoanTime = calculateNewLoanTime(oldLoanTime, monthMappings.get(oldYearMonth));
                    
                    userUpdateBatch.add(new Object[]{newLoanTime, userInfo.getId()});
                    orderTimeMap.put(userInfo.getOrderNumber(), newLoanTime);
                }
            }

            // 批量更新用户信息（使用JDBC批量操作）
            userInfoUpdated = batchUpdateUserInfoByJdbc(userUpdateBatch);
            log.info("用户信息更新完成，共更新 {} 条", userInfoUpdated);

            // ===== 第二步：批量查询并更新还款计划 =====
            log.info("第二步：批量查询还款计划...");
            
            if (!orderTimeMap.isEmpty()) {
                // 一次性查询所有需要更新的订单的还款计划
                List<String> orderNumbers = new ArrayList<>(orderTimeMap.keySet());
                List<MallRepayPlan> allRepayPlans = batchQueryRepayPlans(orderNumbers);
                log.info("查询到 {} 条还款计划记录", allRepayPlans.size());

                // 批量计算新的还款计划数据
                List<Object[]> repayPlanUpdateBatch = new ArrayList<>();
                LocalDateTime cutoffDate = LocalDateTime.of(2025, 9, 30, 23, 59, 59);
                
                for (MallRepayPlan plan : allRepayPlans) {
                    LocalDateTime newLoanTime = orderTimeMap.get(plan.getOrderNumber());
                    if (newLoanTime == null || plan.getPeriodNumber() == null) continue;

                    // 计算新的到期时间
                    LocalDateTime newDueTime = newLoanTime.plusMonths(plan.getPeriodNumber());

                    // 根据到期时间判断状态
                    LocalDateTime newActualRepayTime = null;
                    Integer newRepayStatus;
                    Integer newOverdueDays;
                    
                    if (newDueTime.isBefore(cutoffDate) || newDueTime.isEqual(cutoffDate)) {
                        // 到期时间在2025-09-30之前，按照原状态更新
                        Integer repayStatus = plan.getRepayStatus();
                        Integer overdueDays = plan.getOverdueDays();
                        
                        newRepayStatus = repayStatus;
                        newOverdueDays = overdueDays;

                        if (repayStatus != null) {
                            if (repayStatus == 2) {
                                newActualRepayTime = newDueTime;
                            } else if (repayStatus == 3 && overdueDays != null && overdueDays > 0) {
                                LocalDateTime newRepayTime = newDueTime.plusDays(overdueDays);
                                if (newRepayTime.isBefore(cutoffDate) || newRepayTime.isEqual(cutoffDate)) {
                                    newActualRepayTime = newRepayTime;
                                } else {
                                    newActualRepayTime = cutoffDate;
                                    newOverdueDays = (int) ChronoUnit.DAYS.between(newDueTime, cutoffDate);
                                    newOverdueDays = Math.max(newOverdueDays, 0);
                                }
                            }
                        }
                    } else {
                        // 到期时间在2025-09-30之后，状态改为未到期
                        newRepayStatus = 0;
                        newOverdueDays = 0;
                        newActualRepayTime = null;
                    }

                    repayPlanUpdateBatch.add(new Object[]{
                        newDueTime, newRepayStatus, newOverdueDays, newActualRepayTime, plan.getId()
                    });
                }

                // 批量更新还款计划（使用JDBC批量操作）
                repayPlanUpdated = batchUpdateRepayPlansByJdbc(repayPlanUpdateBatch);
                log.info("还款计划更新完成，共更新 {} 条", repayPlanUpdated);
            }

            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;

            result.setSuccess(true);
            result.setUserInfoUpdated(userInfoUpdated);
            result.setRepayPlanUpdated(repayPlanUpdated);
            result.setDuration(duration);
            result.setMessage(String.format("批量更新成功！用户信息更新 %d 条，还款计划更新 %d 条，耗时 %d ms",
                userInfoUpdated, repayPlanUpdated, duration));

            log.info("========== 批量数据更新完成 ==========");
            log.info("月份映射: {}", monthMappings);
            log.info("用户信息更新: {} 条", userInfoUpdated);
            log.info("还款计划更新: {} 条", repayPlanUpdated);
            log.info("总耗时: {} ms", duration);
            log.info("平均速度: {} 条/秒", (userInfoUpdated + repayPlanUpdated) * 1000 / Math.max(duration, 1));

        } catch (Exception e) {
            log.error("批量更新数据失败", e);
            result.setSuccess(false);
            result.setMessage("批量更新失败: " + e.getMessage());
            throw e;
        }

        return result;
    }

    /**
     * 构建月份映射关系
     */
    private Map<String, String> buildMonthMappings() {
        Map<String, String> mappings = new HashMap<>();
        mappings.put("2024-07", "2024-07");
        mappings.put("2024-08", "2024-08");
        mappings.put("2024-09", "2024-09");
        mappings.put("2024-10", "2024-11");
        mappings.put("2024-11", "2025-03");
        mappings.put("2024-12", "2025-09");
        mappings.put("2025-01", "2025-08");
        mappings.put("2025-02", "2025-07");
        mappings.put("2025-03", "2024-12");
        mappings.put("2025-04", "2025-01");
        mappings.put("2025-05", "2025-02");
        mappings.put("2025-06", "2025-05");
        mappings.put("2025-07", "2025-06");
        mappings.put("2025-08", "2025-04");
        mappings.put("2025-09", "2024-10");
        return mappings;
    }

    /**
     * 计算新的放款时间
     */
    private LocalDateTime calculateNewLoanTime(LocalDateTime oldLoanTime, String newYearMonth) {
        String[] parts = newYearMonth.split("-");
        int newYear = Integer.parseInt(parts[0]);
        int newMonth = Integer.parseInt(parts[1]);
        
        int day = oldLoanTime.getDayOfMonth();
        LocalTime time = oldLoanTime.toLocalTime();
        
        int maxDayInNewMonth = java.time.YearMonth.of(newYear, newMonth).lengthOfMonth();
        if (day > maxDayInNewMonth) {
            day = maxDayInNewMonth;
        }
        
        return LocalDateTime.of(LocalDate.of(newYear, newMonth, day), time);
    }

    /**
     * 批量查询还款计划（一次性查询，避免N+1问题）
     */
    private List<MallRepayPlan> batchQueryRepayPlans(List<String> orderNumbers) {
        if (orderNumbers.isEmpty()) {
            return new ArrayList<>();
        }

        List<MallRepayPlan> allPlans = new ArrayList<>();
        
        // 分批查询，避免IN语句过长（每批1000个订单号）
        for (int i = 0; i < orderNumbers.size(); i += 1000) {
            int end = Math.min(i + 1000, orderNumbers.size());
            List<String> batch = orderNumbers.subList(i, end);
            
            LambdaQueryWrapper<MallRepayPlan> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(MallRepayPlan::getOrderNumber, batch)
                       .orderByAsc(MallRepayPlan::getOrderNumber)
                       .orderByAsc(MallRepayPlan::getPeriodNumber);
            
            List<MallRepayPlan> plans = repayPlanMapper.selectList(queryWrapper);
            allPlans.addAll(plans);
            
            log.debug("批量查询还款计划: {}/{} 订单", end, orderNumbers.size());
        }

        return allPlans;
    }

    /**
     * 使用JDBC批量更新用户信息（性能优化）
     */
    private int batchUpdateUserInfoByJdbc(List<Object[]> updateBatch) {
        if (updateBatch.isEmpty()) {
            return 0;
        }

        String sql = "UPDATE mall_user_info SET loan_time = ? WHERE id = ?";
        int totalUpdated = 0;

        // 分批执行
        for (int i = 0; i < updateBatch.size(); i += BATCH_SIZE) {
            int end = Math.min(i + BATCH_SIZE, updateBatch.size());
            List<Object[]> batch = updateBatch.subList(i, end);

            int[] updateCounts = jdbcTemplate.batchUpdate(sql, batch);
            int batchUpdated = Arrays.stream(updateCounts).sum();
            totalUpdated += batchUpdated;

            log.debug("批量更新用户信息: {}/{}", end, updateBatch.size());
        }

        return totalUpdated;
    }

    /**
     * 使用JDBC批量更新还款计划（性能优化）
     */
    private int batchUpdateRepayPlansByJdbc(List<Object[]> updateBatch) {
        if (updateBatch.isEmpty()) {
            return 0;
        }

        String sql = "UPDATE mall_repay_plan SET due_time = ?, repay_status = ?, " +
                    "overdue_days = ?, actual_repay_time = ? WHERE id = ?";
        int totalUpdated = 0;

        // 分批执行
        for (int i = 0; i < updateBatch.size(); i += BATCH_SIZE) {
            int end = Math.min(i + BATCH_SIZE, updateBatch.size());
            List<Object[]> batch = updateBatch.subList(i, end);

            int[] updateCounts = jdbcTemplate.batchUpdate(sql, batch);
            int batchUpdated = Arrays.stream(updateCounts).sum();
            totalUpdated += batchUpdated;

            if (end % 5000 == 0) {
                log.info("批量更新还款计划: {}/{}", end, updateBatch.size());
            }
        }

        return totalUpdated;
    }

    /**
     * 更新结果类
     */
    public static class UpdateResult {
        private boolean success;
        private String message;
        private int userInfoUpdated;
        private int repayPlanUpdated;
        private long duration;

        public boolean isSuccess() {
            return success;
        }

        public void setSuccess(boolean success) {
            this.success = success;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public int getUserInfoUpdated() {
            return userInfoUpdated;
        }

        public void setUserInfoUpdated(int userInfoUpdated) {
            this.userInfoUpdated = userInfoUpdated;
        }

        public int getRepayPlanUpdated() {
            return repayPlanUpdated;
        }

        public void setRepayPlanUpdated(int repayPlanUpdated) {
            this.repayPlanUpdated = repayPlanUpdated;
        }

        public long getDuration() {
            return duration;
        }

        public void setDuration(long duration) {
            this.duration = duration;
        }
    }
}

